package com.photoeditor.demo.ui.widget.beauty;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.common.base.ComponentContext;
import com.common.base.utils.DeviceUtils;
import com.photoeditor.R;
import com.photoeditor.demo.util.FontUtil;
import com.photoeditor.demo.util.ImageRectUtils;

import java.util.ArrayList;

/**
 * 一键美颜的调整强度的View
 */

public class CustomSeekButton extends View {

    private int mMinHeight;//按钮的最小直径
    private int mMaxHeight = DeviceUtils.dip2px(ComponentContext.getContext(), 32);//按钮的最大直径

    private int mTextDistance;//文本和中间按钮的距离

    private int mMargin;//左右两边的间距

    private int mTextSize;

    private int mProgressHeight;

    private TextPaint mUnselectTextPaint;
    private TextPaint mSelectTextPaint;
    private Paint mUnselectBgPaint;
    private Paint mSelectBgPaint;
    private Paint mUnselectCirclePaint;

    private ArrayList<String> mText;//至少两个
    private ArrayList<RectF> mCircleRect;
    private ArrayList<RectF> mRangeRect;
    private ArrayList<StaticLayout> mTextLayout;
    private ArrayList<StaticLayout> mCheckdTextLayout;

    private RectF mViewRect;
    private boolean mInit;//是否layout完成

    private float mEndTextWidth;//text一行的最大宽度

    private float mTextTop;
    private float mTextBottom;

    private int mCurSelectIndex = 1;

    private float mCurPos;

    private RectF mSelectProgressRect;
    private RectF mUnSelectProgressRect;

    //动画的类
    private ObjectAnimator mAnimator;

    private ISelectListener mSelectedListener;

    public CustomSeekButton(Context context) {
        this(context, null);
    }

    public CustomSeekButton(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomSeekButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mText = new ArrayList<>();
        mRangeRect = new ArrayList<>();
        mCircleRect = new ArrayList<>();
        mTextLayout = new ArrayList<>();
        mCheckdTextLayout = new ArrayList<>();
        mViewRect = new RectF();
        mSelectProgressRect = new RectF();
        mUnSelectProgressRect = new RectF();

        mUnselectTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        mUnselectTextPaint.setTypeface(FontUtil.CUSTOM_FONT);
        mSelectTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        mSelectTextPaint.setTypeface(FontUtil.CUSTOM_FONT);
        mUnselectBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mSelectBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mUnselectCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);//绘制圆环
    }

    /**
     * 初始化
     *
     * @param builder
     */
    public void create(Builder builder) {
        mText.addAll(builder.mText);
        mMinHeight = builder.mMinHeight;
        mMaxHeight = builder.mMaxHeight;
        mTextDistance = builder.mTextDistance;
        mMargin = builder.mMargin;
        mTextSize = builder.mTextSize;
        mProgressHeight = builder.mProgressHeight;

        mUnselectTextPaint.setTextSize(mTextSize);
        mUnselectTextPaint.setColor(getResources().getColor(R.color.image_edit_beauty_unselected_text_color));

        mSelectTextPaint.setTextSize(mTextSize);
        mSelectTextPaint.setColor(getResources().getColor(R.color.accent_color));

        mUnselectBgPaint.setColor(getResources().getColor(R.color.image_edit_beauty_unselected_progress_color));

        mSelectBgPaint.setColor(getResources().getColor(R.color.accent_color));

        mUnselectCirclePaint.setStyle(Paint.Style.STROKE);
        mUnselectCirclePaint.setStrokeWidth(mProgressHeight);
        mUnselectCirclePaint.setColor(getResources().getColor(R.color.image_edit_beauty_unselected_progress_color));
    }

    /**
     * layout完成后计算各个Rect
     *
     * @param viewRect
     */
    private void layoutOver(RectF viewRect) {
        viewRect.offset(-viewRect.left, -viewRect.top);
        if (!mViewRect.equals(viewRect)) {
            mInit = true;
            mViewRect.set(viewRect);
            int buttonSize = mText.size();
            if (buttonSize < 2) return;
            float vH = viewRect.height();
            float vW = viewRect.width();
            float addHeight = (mMaxHeight - mMinHeight) * 1.0f / (buttonSize - 1);
            float addWidth = (vW - (mMargin * 2) - mMaxHeight) / (buttonSize - 1);

            mEndTextWidth = mViewRect.width() / buttonSize;
            mEndTextWidth = Math.min(mEndTextWidth, (mMargin + mMaxHeight / 2) * 2);
            mEndTextWidth = Math.min(mEndTextWidth, addWidth);
            initTextLayout(buttonSize);

            float top = (vH - (mMaxHeight + mTextDistance + mTextLayout.get(0).getHeight())) / 2;
            float bottom = top + mMaxHeight;
            float left = mMargin;
            mTextTop = bottom + mTextDistance;
            mTextBottom = mTextTop + mTextLayout.get(0).getHeight();
            mRangeRect.clear();//清除以前的
            mCircleRect.clear();
            for (int i = 0; i < buttonSize; i++) {
                RectF rangeRect = new RectF();
                RectF circleRect = new RectF();
                float add = addWidth * i;
                float size = (mMinHeight + addHeight * i) / 2;
                rangeRect.set(left + add, top, left + add + mMaxHeight, bottom);
                circleRect.set(rangeRect.centerX() - size, rangeRect.centerY() - size, rangeRect.centerX() + size, rangeRect.centerY() + size);
                mRangeRect.add(rangeRect);
                mCircleRect.add(circleRect);
            }
            mCurPos = mRangeRect.get(mCurSelectIndex).centerX();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
        if (heightMode == MeasureSpec.UNSPECIFIED) {
            if (maxHeight > mMaxHeight) {
                heightMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxHeight, MeasureSpec.EXACTLY);
            }
        }
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int maxWidth = MeasureSpec.getSize(widthMeasureSpec);
        if (widthMode != MeasureSpec.EXACTLY) {
            widthMeasureSpec = MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST);
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (!mInit) {
            layoutOver(ImageRectUtils.getViewRect(this));
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (!mInit) return;
        int size = mRangeRect.size();
        for (int i = 0; i < size; i++) {
            RectF rangeRect = mRangeRect.get(i);
            RectF circleRect = mCircleRect.get(i);
            StaticLayout staticLayout = mTextLayout.get(i);
            if (circleRect.centerX() <= mCurPos) {//绘制成圆形
                if (i != 0) {
                    mSelectProgressRect.set(mCircleRect.get(i - 1).right, circleRect.centerY() - mProgressHeight / 2, mCircleRect.get(i).left, circleRect.centerY() + mProgressHeight / 2);
                    canvas.drawRect(mSelectProgressRect, mSelectBgPaint);
                }
                canvas.drawCircle(circleRect.centerX(), circleRect.centerY(), circleRect.width() / 2, mSelectBgPaint);
                if (circleRect.centerX() == mCurPos) {
                    staticLayout = mCheckdTextLayout.get(i);
                }
            } else {//绘制成圆环mUnselectCirclePaint
                if (i != 0) {
                    RectF circleRectLeft = mCircleRect.get(i - 1);
                    if (circleRectLeft.right > mCurPos) {//在左边的内部
                        mUnSelectProgressRect.set(circleRectLeft.right, circleRect.centerY() - mProgressHeight / 2, circleRect.left, circleRect.centerY() + mProgressHeight / 2);
                        canvas.drawRect(mUnSelectProgressRect, mUnselectBgPaint);
                    } else if (circleRect.left <= mCurPos) {//在右边的左半部分
                        mSelectProgressRect.set(circleRectLeft.right, circleRect.centerY() - mProgressHeight / 2, circleRect.left, circleRect.centerY() + mProgressHeight / 2);
                        canvas.drawRect(mSelectProgressRect, mSelectBgPaint);
                    } else {
                        mSelectProgressRect.set(circleRectLeft.right, circleRect.centerY() - mProgressHeight / 2, mCurPos, circleRect.centerY() + mProgressHeight / 2);
                        canvas.drawRect(mSelectProgressRect, mSelectBgPaint);
                        mUnSelectProgressRect.set(mCurPos, circleRect.centerY() - mProgressHeight / 2, circleRect.left, circleRect.centerY() + mProgressHeight / 2);
                        canvas.drawRect(mUnSelectProgressRect, mUnselectBgPaint);
                    }
                }
                canvas.drawCircle(circleRect.centerX(), circleRect.centerY(), (circleRect.width() / 2 - mProgressHeight / 2), mUnselectCirclePaint);
            }
            float left = rangeRect.centerX() - staticLayout.getLineWidth(0) / 2;
            int flag = canvas.save();
            canvas.translate(left, mTextTop);
            staticLayout.draw(canvas);
            canvas.restoreToCount(flag);
        }
        if (mAnimator != null && mAnimator.isRunning()) {//则在当前位置绘制一个圆
            float radius = mMinHeight + (mCurPos - mRangeRect.get(0).centerX()) / (mViewRect.width() - (mMargin * 2) - mMaxHeight) * (mMaxHeight - mMinHeight);
            canvas.drawCircle(mCurPos, mRangeRect.get(0).centerY(), radius / 2, mSelectBgPaint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!mInit) return super.onTouchEvent(event);
        int action = event.getAction();
        if (action == MotionEvent.ACTION_DOWN) {
            return true;
        } else if (action == MotionEvent.ACTION_UP) {
            float x = event.getX();
            float y = event.getY();
            for (int i = 0; i < mRangeRect.size(); i++) {
                RectF rect = mRangeRect.get(i);
                if (x <= rect.right && x >= rect.left && y <= mTextBottom && y >= rect.top) {
                    setCurSelectIndex(i, true, true);
                    break;
                }
            }
        }
        return super.onTouchEvent(event);
    }

    /**
     * 刷新text Layout
     *
     * @param size
     */
    private void initTextLayout(int size) {
        for (int i = 0; i < size; i++) {
            String text = mText.get(i);
            float maxWidth = StaticLayout.getDesiredWidth(text, mUnselectTextPaint);
            StaticLayout textLayout = new StaticLayout(text, 0, text.length(), mUnselectTextPaint, (int) (maxWidth + 1),
                    Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.END, (int) (mEndTextWidth + 1));
            mTextLayout.add(textLayout);

            maxWidth = StaticLayout.getDesiredWidth(text, mSelectTextPaint);
            StaticLayout checkedTextLayout = new StaticLayout(text, 0, text.length(), mSelectTextPaint, (int) (maxWidth + 1),
                    Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.END, (int) (mEndTextWidth + 1));
            mCheckdTextLayout.add(checkedTextLayout);
        }
    }

    public int getCurSelectIndex() {
        return mCurSelectIndex;
    }

    public void setCurSelectIndex(int curSelectIndex, boolean animation) {
        setCurSelectIndex(curSelectIndex, animation, false);
    }

    private void setCurSelectIndex(int curSelectIndex, boolean animation, boolean user) {
        if (mSelectedListener != null) {
            boolean canSelected = mSelectedListener.onSelected(user, curSelectIndex);
            if (canSelected) {
                this.mCurSelectIndex = curSelectIndex;
            }
        } else {
            this.mCurSelectIndex = curSelectIndex;
        }
        if (mInit) {
            if (animation) {
                doAnimation(mCurSelectIndex);
            } else {
                if (mAnimator != null) {
                    mAnimator.cancel();//停止在当前状态
                }
                setCurPos(mRangeRect.get(mCurSelectIndex).centerX());
            }
        }
    }

    private void doAnimation(int curIndex) {
        float curCenterX = mRangeRect.get(curIndex).centerX();
        if (mAnimator == null) {
            mAnimator = ObjectAnimator.ofFloat(this, "curPos", getCurPos(), curCenterX).setDuration(300);
        } else {
            mAnimator.cancel();//停止在当前状态
            mAnimator.setFloatValues(getCurPos(), curCenterX);
        }
        mAnimator.start();
    }

    private float getCurPos() {
        return mCurPos;
    }

    private void setCurPos(float curPos) {
        this.mCurPos = curPos;
        invalidate();
    }

    public void setSelectedListener(ISelectListener mSelectedListener) {
        this.mSelectedListener = mSelectedListener;
    }

    /**
     * 传入参数的Builder
     */
    public static class Builder {
        ArrayList<String> mText;

        int mMinHeight = DeviceUtils.dip2px(ComponentContext.getContext(), 20);

        int mMaxHeight = DeviceUtils.dip2px(ComponentContext.getContext(), 32);

        int mTextDistance = DeviceUtils.dip2px(ComponentContext.getContext(), 8);//文本和中间按钮的距离

        int mMargin = DeviceUtils.dip2px(ComponentContext.getContext(), 48);//左右两边的间距

        int mTextSize = (int) DeviceUtils.sp2pxF(ComponentContext.getContext(), 12);

        int mProgressHeight = DeviceUtils.dip2px(ComponentContext.getContext(), 2);

        public Builder() {
            mText = new ArrayList<>();
        }

        public Builder addButton(String text) {
            mText.add(text);
            return this;
        }

        public Builder minHeight(int minHeight) {
            mMinHeight = minHeight;
            return this;
        }

        public Builder maxHeight(int maxHeight) {
            mMaxHeight = maxHeight;
            return this;
        }

        public Builder textDistance(int textDistance) {
            mTextDistance = textDistance;
            return this;
        }

        public Builder margin(int margin) {
            mMargin = margin;
            return this;
        }

        public Builder textSize(int textSize) {
            mTextSize = textSize;
            return this;
        }

        public Builder progressHeight(int progressHeight) {
            mProgressHeight = progressHeight;
            return this;
        }
    }

    public interface ISelectListener {
        boolean onSelected(boolean user, int index);
    }
}
